#ifndef N_GEOMETRYNODE_H
#define N_GEOMETRYNODE_H
//------------------------------------------------------------------------------
/**
    @class nGeometryNode
    @ingroup SceneNodes

    @brief A geometry node is an abstract node that encapsulates the
    functionality of all nodes containing renderable geometry.
    
    It is derived from nAbstractShaderNode, and thus inherits shader parameters.
    It must be assigned a surface, from which it inherits its render passes.

    See also @ref N2ScriptInterface_ngeometrynode
    
    (C) 2004 Conjurer Services, S.A.
*/
#include "nscene/nabstractshadernode.h"
#include "kernel/ndynautoref.h"
#include "util/nmaptabletypes.h"
#include "util/nsafekeyarray.h"

class nSurfaceNode;

//------------------------------------------------------------------------------
class nGeometryNode : public nAbstractShaderNode
{
public:
    /// constructor
    nGeometryNode();
    /// destructor
    virtual ~nGeometryNode();
    /// object persistency
    virtual bool SaveCmds(nPersistServer *ps);
    /// load resources
    virtual bool LoadResources();
    /// unload resources
    virtual void UnloadResources();
    /// called by app when new render context has been created for this object
    virtual void RenderContextCreated(nRenderContext* renderContext);
    /// called by app when render context is going to be released
    virtual void RenderContextDestroyed(nRenderContext* renderContext);
    /// called by nSceneGraph when object is attached to scene
    virtual void Attach(nSceneGraph* sceneGraph, nRenderContext* renderContext);
    /// perform pre-instancing rendering of geometry
    virtual bool Apply(nSceneGraph* sceneGraph);
    /// render geometry
    virtual bool Render(nSceneGraph* sceneGraph, nRenderContext* renderContext);
    /// perfor post-instancing rendering of geometry
    virtual bool Flush(nSceneGraph* sceneGraph);

    /// set the surface
    void SetSurface(const char *relPath);
    /// get the surface
    const char *GetSurface();
    /// set whether the geometry is in world coordinates
    void SetWorldCoord(bool worldCoord);
    /// get whether the geometry is in world coordinates
    bool GetWorldCoord();

protected:

    nDynAutoRef<nSurfaceNode> refSurfaceNode;

    bool worldCoord;
    uint geometryId;
    uint streamId;
    int streamIndex;
    static uint uniqueGeometryId;
};

//------------------------------------------------------------------------------
/**
    Specifies the surface node for this geometry.
*/
inline
void
nGeometryNode::SetSurface(const char *relPath)
{
    this->refSurfaceNode.set(relPath);
    this->resourcesValid = false;
}

//------------------------------------------------------------------------------
/**
    Get path to surface node.
*/
inline
const char*
nGeometryNode::GetSurface()
{
    return this->refSurfaceNode.getname();
}

//------------------------------------------------------------------------------
/**
    Set whether the geometry handles its own coordinates.
*/
inline
void
nGeometryNode::SetWorldCoord(bool worldCoord)
{
    this->worldCoord = worldCoord;
}

//------------------------------------------------------------------------------
/**
    Get whether the geometry handles its own coordinates.
*/
inline
bool
nGeometryNode::GetWorldCoord()
{
    return this->worldCoord;
}

//------------------------------------------------------------------------------
#endif
